package com.distribute.framework.core.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;

import com.alibaba.fastjson.JSON;


public class CometServlet extends HttpServlet implements CometProcessor{

	private static final long serialVersionUID = 1L;
	
	private static final long wait_time_seconds = 10;//等待保留时间
	
	static Map<String,HttpServletResponse> responses = new HashMap();	
	public static class CometWait{
		public Date time = new Date();
		public Queue queue = new LinkedList();
	}
	static Map<String,CometWait> waits = new HashMap();//等待保留池
	private Object getWaitData(String sid) {
		CometWait cometWait = waits.get(sid);
		if(cometWait==null)return null;
		if((new Date().getTime()-cometWait.time.getTime())>(wait_time_seconds*1000)){
			waits.remove(sid);			
			return null;
		}
		cometWait.time=new Date();
		return cometWait.queue.poll();
	}
	
	public static void send(Object data,String... ids){
			if(ids.length==0){
				ids = responses.keySet().toArray(new String[]{});
			}
			synchronized (responses){
				for(String sid:ids){
					sendData(responses.get(sid),data);
					remove(sid);
				}
			}
			{
				String[] keys = waits.keySet().toArray(new String[]{});
				for(String sid:keys){
					CometWait cometWait = waits.get(sid);
					if(cometWait==null)continue;
					if((new Date().getTime()-cometWait.time.getTime())>(wait_time_seconds*1000)){
						waits.remove(sid);			
						continue;
					}
					waits.get(sid).queue.add(data);
				}
			}
		
	}
	public static void sendData(HttpServletResponse response,Object data){
		try {
			if(response==null)return;
			response.setCharacterEncoding("UTF-8");
			PrintWriter writer = response.getWriter();
			writer.write(JSON.toJSONString(data));
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	private static void remove(String sid) {
		synchronized (responses){
			try { 
				if(responses.get(sid)!=null){
					if(!responses.get(sid).isCommitted()){
						responses.get(sid).getWriter().flush();
					}
					responses.get(sid).getWriter().close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			responses.remove(sid);
			waits.put(sid, new CometWait());
		}
	}
	public void event(CometEvent event) throws IOException, ServletException {
		 String sid = (String) event.getHttpServletRequest().getSession().getId();
		 if(event.getEventType() == CometEvent.EventType.BEGIN) { 
			 if(responses.get(sid)!=null){
				 remove(sid);
			 }
			 Object waitData = getWaitData(sid);
			 if(waitData!=null){//如果有列表数据，则直接发数据
				 sendData(event.getHttpServletResponse(),waitData);
			 }else{//否则排队
				 responses.put(sid,event.getHttpServletResponse());
			 }
		 } else if (event.getEventType() == CometEvent.EventType.ERROR) {
			 remove(sid);
         }else if (event.getEventType() == CometEvent.EventType.END) {
        	remove(sid);
         }else if (event.getEventSubType()== CometEvent.EventSubType.SESSION_END) {
        	remove(sid);
         }
	}
	
	
}